import math

import numpy as np
import matplotlib.pyplot as plt

# 端点和控制点
P0 = np.array([1.0, 0.0])
P1 = np.array([2.0, -1.0])
P2 = np.array([3.0, -1.0])
P3 = np.array([4.0, 2.0])

def bezier(t, ctrl_pts):
    """
    通用 Bézier 曲线点计算
    参数
    ----
    t : float 或 ndarray，取值范围 [0, 1]
    ctrl_pts : ndarray，形状为 (m, d)
               m 为控制点数，d 为维度（2D、3D 等）
    返回
    ----
    point : ndarray，形状为 (d,)（若 t 为标量）或 (len(t), d)（若 t 为数组）
    """
    ctrl_pts = np.asarray(ctrl_pts, dtype=float)
    n = ctrl_pts.shape[0] - 1          # 曲线次数
    t = np.asarray(t, dtype=float)

    # 标量情况
    point = np.zeros(ctrl_pts.shape[1])
    for i in range(n + 1):
        point += math.comb(n, i) * (1 - t) ** (n - i) * t ** i * ctrl_pts[i]
    return point


if __name__ == '__main__':

    # 生成 t 参数
    t_vals = np.linspace(0, 1, 200)
    curve = np.array([bezier(t, [P0, P1, P2, P3]) for t in t_vals])
    # 绘图
    plt.figure(figsize=(6, 6))
    # 贝塞尔曲线
    plt.plot(curve[:, 0], curve[:, 1], 'b-', label='Bezier curve')
    # 控制多边形
    control_pts = np.vstack([P0, P1, P2, P3])
    plt.plot(control_pts[:, 0], control_pts[:, 1], 'k--', marker='o',
             label='Control polygon')
    plt.title('Cubic Bézier Curve')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.axis('equal')
    plt.grid(True)
    plt.legend()
    plt.show()
